<template>
  <div class="notice">
    <!-- 搜索栏 -->
    <div class="search-container">
      <el-input
        placeholder="请输入公告名称搜索"
        v-model="searchKeyword"
        prefix-icon="el-icon-search"
        class="search-input"
        @input="searchNotice"
      ></el-input>
    </div>

    <el-table
      :data="filteredNoticeData"
      style="width: 100%"
      v-loading="loading"
    >
      <el-table-column
        prop="number"
        label="公告编号"
        width="180"
      ></el-table-column>

      <el-table-column
        prop="title"
        label="公告名称"
        width="180"
      ></el-table-column>

      <el-table-column
        prop="content"
        label="公告内容"
        width="180"
      ></el-table-column>

      <el-table-column
        label="公告日期"
        width="180"
      >
        <template #default="{ row }">
          {{ formatDate(row.noticedate) }}
        </template>
      </el-table-column>
      <el-table-column
        label="图片"
        width="150"
      >
        <template #default="{ row }">
          <el-image 
            v-if="row.image"
            :src="require('@/assets/' + row.image)" 
            class="notice-image"
            :preview-src-list="[row.imageUrl]"
          >
            <div slot="error" class="image-slot">
              <i class="el-icon-picture-outline"></i>
            </div>
          </el-image>
          <span v-else class="no-image">无图片</span>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        width="120"
      >
        <template #default="{ row, $index }">
          <el-upload
            class="upload-container"
            action=""
            :show-file-list="false"
            :http-request="handleUpload"
            :before-upload="beforeAvatarUpload"
          >
            <el-tooltip content="上传图片" placement="top">
              <el-button 
                type="primary" 
                icon="el-icon-upload" 
                size="mini"
                :disabled="row.number === currentUploadId && isUploading"
                @click="setCurrentNotice(row.number, $index)"
              ></el-button>
            </el-tooltip>
          </el-upload>
          <el-button
            v-if="row.imageUrl"
            type="danger"
            icon="el-icon-delete"
            size="mini"
            @click="deleteNoticeImage(row.number, $index)"
          ></el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 上传进度对话框 -->
    <el-dialog
      title="图片上传中"
      :visible.sync="uploadDialogVisible"
      width="30%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <el-progress :percentage="uploadPercentage"></el-progress>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancelUpload">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios';

const instance = axios.create({
  baseURL: 'http://localhost:9084', // 设置基础 URL
  timeout: 10000
});

export default {
  data() {
    return {
      noticeData: [],
      dialogVisible: false,
      editForm: {},
      editIndex: -1,
      searchKeyword: '',
      loading: false,
      isUploading: false,
      currentUploadId: 0,
      currentUploadIndex: null,
      uploadDialogVisible: false,
      uploadPercentage: 0,
      cancelTokenSource: null
    };
  },
  computed: {
    filteredNoticeData() {
      if (!this.searchKeyword) return this.noticeData;
      const keyword = this.searchKeyword.toLowerCase();
      return this.noticeData.filter(item => 
        item.title.toLowerCase().includes(keyword)
      );
    }
  },
  mounted() {
    this.fetchNotice();
  },
  methods: {
    // 设置当前正在上传的公告
    setCurrentNotice(id, index) {
      this.currentUploadId = id;
      this.currentUploadIndex = index;
    },
    // 上传前的处理
    beforeAvatarUpload(file) {
      const isJPGOrPNG = file.type === 'image/jpeg' || file.type === 'image/png';
      const isLt2M = file.size / 1024 / 1024 < 2;

      if (!isJPGOrPNG) {
        this.$message.error('上传图片只能是 JPG/PNG 格式!');
      }
      if (!isLt2M) {
        this.$message.error('上传图片大小不能超过 2MB!');
      }
      
      if (isJPGOrPNG && isLt2M) {
        this.uploadDialogVisible = true;
      }
      
      return isJPGOrPNG && isLt2M;
    },
    // 上传处理函数
    handleUpload({ file }) {
      const formData = new FormData();
      formData.append('image', file);
      formData.append('noticeId', this.currentUploadId);
      
      this.isUploading = true;
      
      // 创建取消令牌
      this.cancelTokenSource = axios.CancelToken.source();
      
      instance.post('/api/notice/upload-image', formData, {
        cancelToken: this.cancelTokenSource.token,
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: progressEvent => {
          this.uploadPercentage = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
        }
      }).then(response => {
        if (response.status === 200) {
          // 更新本地数据
          // if (this.currentUploadIndex !== null) {
          //   this.noticeData[this.currentUploadIndex].imageUrl = 
          //     this.processImageUrl(response.data.imageUrl);
          // }
          this.fetchNotice();
          this.$message.success('图片上传成功！');
          // 关闭对话框并重置状态
          setTimeout(() => {
            this.resetUploadStatus();
          }, 500);
        }
      }).catch(error => {
        if (axios.isCancel(error)) {
          this.$message.warning('图片上传已取消');
        } else {
          this.handleApiError(error, '图片上传失败');
        }
        this.resetUploadStatus();
      });
    },
    // 删除公告图片
    async deleteNoticeImage(noticeId, index) {
      try {
        this.$confirm('确定要删除这张图片吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(async () => {
          const response = await instance.delete(`/api/notice/image/${noticeId}`);
          if (response.status === 200) {
            this.$message.success('图片删除成功');
            // 更新本地数据
            if (index !== null) {
              this.$set(this.noticeData[index], 'imageUrl', null);
            }
          }
        }).catch(() => {
          // 取消删除
        });
      } catch (error) {
        this.handleApiError(error, '图片删除失败');
      }
    },
    // 取消上传
    cancelUpload() {
      if (this.cancelTokenSource) {
        this.cancelTokenSource.cancel('用户取消了上传');
      }
      this.resetUploadStatus();
    },
    // 重置上传状态
    resetUploadStatus() {
      this.isUploading = false;
      this.currentUploadId = null;
      this.currentUploadIndex = null;
      this.uploadDialogVisible = false;
      this.uploadPercentage = 0;
      this.cancelTokenSource = null;
    },
    async fetchNotice() {
      try {
        this.loading = true;
        const response = await instance.get('/api/notice'); 
        if (response.status === 200) {
          this.noticeData = response.data;
        } else {
          console.error('获取公告信息失败，状态码:', response.status);
          this.$message.error('获取公告信息失败，状态码: ' + response.status);
        }
      } catch (error) {
        if (error.response) {
          console.error('获取公告信息失败，服务器返回错误:', error.response.data);
          this.$message.error('获取公告信息失败，服务器返回错误: ' + JSON.stringify(error.response.data));
        } else if (error.request) {
          console.error('获取公告信息失败，没有收到服务器响应:', error.request);
          this.$message.error('获取公告信息失败，没有收到服务器响应');
        } else {
          console.error('获取公告信息失败，请求设置错误:', error.message);
          this.$message.error('获取公告信息失败，请求设置错误: ' + error.message);
        }
      } finally {
        this.loading = false;
      }
    },
    async searchNotice() {
      if (!this.searchKeyword) {
        // 搜索关键词为空时，直接使用已有数据
        return;
      }
      try {
        this.loading = true;
        const response = await instance.get(`/api/notice/title/${this.searchKeyword}`);
        if (response.status === 200) {
          this.noticeData = [response.data]; // 搜索结果应该是单个对象，包装成数组
        } else {
          console.error('搜索公告信息失败，状态码:', response.status);
          this.$message.error('搜索公告信息失败，状态码: ' + response.status);
        }
      } catch (error) {
        if (error.response) {
          console.error('搜索公告信息失败，服务器返回错误:', error.response.data);
          this.$message.error('搜索公告信息失败，服务器返回错误: ' + JSON.stringify(error.response.data));
        } else if (error.request) {
          console.error('搜索公告信息失败，没有收到服务器响应:', error.request);
          this.$message.error('搜索公告信息失败，没有收到服务器响应');
        } else {
          console.error('搜索公告信息失败，请求设置错误:', error.message);
          this.$message.error('搜索公告信息失败，请求设置错误: ' + error.message);
        }
      } finally {
        this.loading = false;
      }
    },
    formatDate(dateString) {
      const date = new Date(dateString);
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      const hours = String(date.getHours()).padStart(2, '0');
      const minutes = String(date.getMinutes()).padStart(2, '0');
      const seconds = String(date.getSeconds()).padStart(2, '0');
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    }
  }
};
</script>

<style scoped>
.notice {
  padding: 20px;
}

.search-container {
  margin-bottom: 20px;
  display: flex;
  align-items: center;
}

.search-input {
  width: 300px;
  margin: 0 auto;
  margin-right: 10px; /* 为按钮留出间距 */
}

.el-table {
  margin-top: 15px;
  background-color: white;
}

.el-table__header {
  background-color: #f8f9fa;
}

.el-popover {
  max-width: 300px;
}

.upload-container {
  display: inline-block;
  margin-right: 8px;
}

.notice-image {
  width: 120px;
  height: 90px;
  border-radius: 4px;
  background-color: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.notice-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-slot {
  font-size: 30px;
  color: #c0c4cc;
}

.no-image {
  color: #909399;
  font-size: 12px;
}
</style>